几个月前面试的时候问我性能优化我可能会开始背诵雅虎军规,加点
webp
,代码层面稍稍讲点,现在系统的梳理下性能优化的方方面面
本文涉及方面有:
代码优化
-
网络请求过程角度入手
DNS
解析TCP
建立链接网络往返时延(
RTT
)数据传输
-
网络问题角度入手
请求数量
流量
性能优化测试工具
代码优化
css
代码优化
避免类正则的属性选择器
CSS3
添加了复杂的属性选择器,可以通过类正则表达式的方式对元素的属性值进行匹配。当然这些类型的选择器定是会影响性能的,正则表达式匹配会比基于类别的匹配会慢很多。大部分情况下我们应尽量避免使用 *=, |=, ^=, $=, 和 ~=语法的属性选择器。
合写CSS
除了压缩的方式,我们还可以通过少写CSS属性来达到减少CSS字节的目的
利用继承CSS
css
的继承机制也可以帮我们再一定程度上缩减字节数,我们知道CSS有很多属性是可以继承的即在父容器设置了默写属性,子容器会默认也使用这些属性,因此如果我们希望全文字体尺寸是14px,大可不必为每个容器设置,只需要在body上设置就可以了。应用这个技巧,把CSS属性在可能的情况下提到父容器是可以帮我们节省CSS字节的,顺便说一下哪些属性可以继承
所有元素可继承:
visibility
和cursor
内联元素和块元素可继承:
letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction
块状元素可继承:
text-indent
和text-align
列表元素可继承:
list-style、list-style-type、list-style-position、list-style-image
表格元素可继承:
border-collapse
不可继承的:
display、margin、border、padding、background、height、min-height、max- height、width、min-width、max-width、overflow、position、left、right、top、 bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、 page-bread-before
不用CSS
表达式
不乱用CSS reset
或属性设置
避免适用通配符或隐式通配符
javascript
代码优化
尽量使用原生方法
javaScript是解释性语言,相比编译性语言执行速度要慢。浏览器已经实现的方法,就不要再去实现一遍了。另外,浏览器已经实现的方法在算法方面已经做了很多优化
不要类型转换
JavaScript
是动态类型,但如果你想提高速度不要使用该功能。尽量保持变量的类型一致。这也适用于数组,尽管主要是由浏览器都进行了优化,但尽量不要混用不同类型的数组
避免使用不支持的语法
优化编译器不支持一些特定的语句, 使用这些语法会使包含它的函数无法得到优化.
有一点请注意, 即使这些语句无法到达或者不会被执行, 它们也会使相关函数无法被优化
目前不会被优化的有:
generator
函数包含
for...of
语句的函数包含
try...catch
的函数包含
try...finally
的函数包含复合
let
赋值语句的函数 (原文为 compound let assignment)包含复合
const
赋值语句的函数 (原文为 compound const assignment)包含含有
__proto__
或者get/set
声明的对象字面量的函数
可能永远不会被优化的有:
包含
debugger
语句的函数包含字面调用
eval()
的函数包含
with
语句的函数
处理方法
之前提到过的一些语句在生产环境中是无法避免的, 比如 try...finally
和 try...catch
. 为了是代价最小, 它们必须被隔离到一个最小化的函数, 以保证主要的代码不受影响.
使用微类库
通常开发者都会使用JavaScript
类库,如jQuery、Mootools、YUI、Dojo
等,但是开发者往往只是使用JavaScript
类库中的部分功能。为了更大的提升性能,应尽量避免使用这类大而全的类库,而是按需使用微类库来辅助开发
用做标记的变量尽可能使用布尔类型
直接用true和false做标记,不要使用数字或者字符串的1和0来做标记。
jquery
最佳实践
网络请求角度入手
正常的一次网络请求会经历4个过程,分别是:
DNS
解析 ->TCP
建立链接 -> 网络往返时延(RTT
) -> 数据传输,面临的挑战可以总结为时延较高、带宽有限、流量有成本,具体各过程面临的挑战和优化措施如下。
-
DNS
解析主要挑战:解析耗时长
-
优化措施
减少域名
首屏在3个域名内
-
减少
DNS
查找,避免重定向。浏览器DNS
缓存 、计算机DNS
缓存、 服务器DNS
缓存、使用Keep-Alive
特性 来减少DNS
查找。
参考资料: DNS解析
-
TCP
连接主要挑战:除了TCP握手会多一次网络往返,另外在移动端网络建立
TCP
链接前,还需要进行信令的交互,在2G环境下影响最为明显-
优化措施(复用)
-
HTTP2.0
多路复用HTTP/2
可以很容易的去实现多流并行而不用依赖建立多个 TCP 连接,HTTP/2 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上双向交换消息。单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大 由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快
HTTP1.1
持久连接
-
参考资料:知乎HTTP2.0
-
网络往返时延(
RTT
)主要挑战:耗时长
-
优化措施(复用、合并、就近接入)
-
就近接入
静态资源:接入
CDN
动态数据
接入移动运营商和小运营商反向代理进行加速
-
合并请求,减少请求数量
首屏禁止301、302跳转
合并样式和脚本
使用
css
图片精灵首屏必须小图片使用
base64
格式内嵌入HTML
初始首屏之外的图片资源按需加载,静态资源延迟加载
合并外联代码
-
缓存
抽出公共代码复用缓存
使用
LocalStorage
等缓存数据图片/外链代码开启缓存
-
参考资料:知乎合并 HTTP 请求是否真的有意义?
-
数据传输
主要挑战:带宽有限、流量有成本
-
优化措施(复用、压缩、分包)
-
压缩
-
图片优化
不需要背景透明的采用jpg代替png 使用webp 使用合适尺寸的图片,而不是对图片进行拉伸
开启
GZIP
压缩代码
静态资源使用不带
cookie
的域名
-
复用
HTTP 304
-
网络问题角度入手
页面在网络上遇到的问题可以总结为一个或多个网络请求以及每个请求的流量问题,在请求数量以及每个请求的流量固定的情况下,可以通过优化请求顺序以及合理划分流量来提升用户体验,请求顺序和流量划分通常遇到的问题和优化措施如下。
请求
主要挑战:
没有充分利用有限的并发数量,串行加载数据
可以预先加载的操作没有预先加载
无用请求抢占并发数量-
优化
-
DNS
的预解析
可以通过用meta
信息来告知浏览器, 我这页面要做DNS预解析<meta http-equiv="x-dns-prefetch-control" content="on" />
可以使用link标签来强制对DNS做预解析:
<link rel="dns-prefetch" href="http://ke.qq.com/" />
HTTP
管线化
HTTP管线化可以克服同域并行请求限制带来的阻塞,它是建立在持久连接之上,是把所有请求一并发给服务器,但是服务器需要按照顺序一个一个响应,而不是等到一个响应回来才能发下一个请求,这样就节省了很多请求到服务器的时间。不过,HTTP管线化仍旧有阻塞的问题,若上一响应迟迟不回,后面的响应都会被阻塞到。删除无用请求
-
-
流量
主要挑战:各种流量混在一起加载,流量之间没有优先级
-
优化措施(延迟加载)
延迟加载非首屏代码(拆分首屏css,首屏js)
延迟加载非首屏数据
懒加载,屏幕滚动到才加载延迟加载非首屏图片
轮播图片等第一张图片加载后再加载后面其他图片
网站性能工具
YSLOW
会按照雅虎军规分析网站
Page Speed Online
Google Page Speed 是当下很流行的在线测试网站性能工具,基于Google的一套最佳的前端性能的规则,你可以很方便得到大量的性能信息,甚至还提供了移动设备的最佳实践报告。
Show Slow
它能从三个流行的测试工具YSlow,Page Speed和DynaTrace定期获取测试数据进行总结对比,免费,但需要注册。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。